package gu.sql2java.json;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static gu.sql2java.transformer.ColumnTransformer.INTERGRAL_CLASSES;

import java.io.IOException;
import java.util.Collection;
import java.util.Set;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.google.common.base.Function;

/**
 * @author guyadong
 * @since 3.27.0
 */
public class IntegralbitsJacksonCodec {

	/**
	 * (枚举)字符串集合反序列化为整数(Long|Integer)的实现
	 */
	public static class Deserializer<T> extends JsonDeserializer<T> {
		private final Class<T> type;
		@SuppressWarnings("rawtypes")
		private final Function<Collection, T> agg;
		/**
		 * @param type 数字类型(Long|Integer|Short|Byte)
		 * @param agg 将字符串集合聚合为整数的函数
		 */
		@SuppressWarnings("rawtypes")
		public Deserializer (Class<T>type,Function<Collection, T> agg) {
			this.type = checkNotNull(type,"type is null");
			checkArgument(INTERGRAL_CLASSES.contains(type),
					"Long , Integer, Short or Byte type required");
			this.agg = checkNotNull(agg,"agg is null");
		}
		@Override
		public T deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
	        ObjectMapper mapper = (ObjectMapper) jp.getCodec();
	        try {
	        	return mapper.readValue(jp, type);
			} catch (IOException e) {
				Set<String> node = mapper.readValue(jp,new TypeReference<Set<String>>(){});
				return agg.apply(node);
			}
		}

	}
	/**
	 * 整数(Long|Integer)序列化为(枚举)字符串集合的实现
	 */
	public static class Serializer<T> extends JsonSerializer<T> {
		private final Function<T, Set<String>> split;
		/**
		 * @param type 数字类型(Long|Integer|Short|Byte)
		 * @param split 将整数拆分为字符串集合的函数
		 */
		public Serializer (Class<T>type,Function< T,Set<String>> split) {
			checkNotNull(type,"type is null");
			checkArgument(INTERGRAL_CLASSES.contains(type),
					"Long , Integer, Short or Byte type required");
			this.split = checkNotNull(split,"split is null");
		}
		@Override
		public void serialize(T value, JsonGenerator gen, SerializerProvider serializers)
				throws IOException, JsonProcessingException {
			gen.writeStartArray();
			for(String name:split.apply(value)) {
				gen.writeString(name);
			}
			gen.writeEndArray();
		}

	}
}
